package com.edu.app.shiro;

import com.edu.app.bean.core.SysPermission;
import com.edu.app.bean.core.SysRole;
import com.edu.app.bean.core.SysTenant;
import com.edu.app.bean.core.SysUser;
import com.edu.app.service.sys.core.SysTenantService;
import com.edu.app.service.sys.core.SysUserService;
import com.edu.app.service.sys.linkservices.SysRolePermissionService;
import com.edu.app.service.sys.linkservices.SysUserRoleService;
import com.edu.app.threadlocal.TenantContext;
import com.edu.app.util.JWTUtil;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class MyShiroRealm extends AuthorizingRealm {
    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserRoleService sysUserRoleService;

    @Resource
    private SysRolePermissionService sysRolePermissionService;

    @Resource
    private SysTenantService sysTenantService;

    /**
     * 大坑！，必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String token  = (String)principals.getPrimaryPrincipal();
        String username = JWTUtil.getUsername(token);
        SysUser sysUser = sysUserService.getUserByName(username);
        for(SysRole role:sysUserRoleService.getRoleListByUserId(sysUser.getId())){
            authorizationInfo.addRole(role.getRole_name());
            for(SysPermission p:sysRolePermissionService.getPermissionListByRoleId(role.getId())){
                authorizationInfo.addStringPermission(p.getPermission());
            }
        }
        return authorizationInfo;
    }

    /*主要是用来进行身份认证的，也就是说验证用户输入的账号和密码是否正确。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth)
            throws AuthenticationException {
        try{
            String token = (String) auth.getCredentials();
            // 解密获得username，用于和数据库进行对比
            String username = JWTUtil.getUsername(token);
            if (username == null) {
                throw new AuthenticationException("token invalid");
            }

            TenantContext.setNeedTenantId(Boolean.FALSE);
            SysUser sysUser = sysUserService.getUserByName(username);
            if (sysUser == null) {
                throw new AuthenticationException("User didn't existed!");
            }
            if(sysUser.getStatus() == 0){
                throw new AuthenticationException("User is not active!");
            }

            if (! JWTUtil.verify(token, username, sysUser.getPassword())) {
                throw new AuthenticationException("Username or password error");

            }
            Integer tenant_id = sysUser.getTenant_id();

            SysTenant tenant = sysTenantService.getObjectById(tenant_id);
            //if(tenant == null)
            //    throw new AuthenticationException("Not a valid user");
            TenantContext.setCurrentTenant(tenant);

            return new SimpleAuthenticationInfo(token, token, "my_realm");
        }finally {
            TenantContext.setNeedTenantId(Boolean.TRUE);
        }
    }
}